package io.tim.mvc_f2.helper;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Map.Entry;

import io.tim.mvc_f2.annotation.Inject;
import io.tim.mvc_f2.util.ArrayUtil;
import io.tim.mvc_f2.util.CollectionUtil;
import io.tim.mvc_f2.util.ReflectionUtil;

import java.util.Set;

/**
 * 依赖注入助手类
 *
 * @author zhangnan
 * @date 2017年3月10日
 *
 */
public final class IOCHelper {

	static {
		/**
		 * 依赖注入的步骤：
		 * 1、通过 BeanHelper 获取所有的 Bean Map（即所有 Bean 的类与对象的映射关系）
		 * 2、遍历 Bean Map 分别取出 Bean 类与 Bean 实例
		 * 3、通过反射获取 Bean 类中所有的成员变量
		 * 4、遍历这些成员变量，在循环中判断当前成员变量是否带有 Inject 注解，若带有该注解，则从 Bean Map 中根据 Bean 类取出 Bean 实例。
		 * 5、通过 ReflectionUtil#setField 方法来修改当前成员变量的值
		 * 注：无论是 Controller 类还是其中被应用了 Inject 注解的成员变量，它们的实例都来自于 Bean Map，都是单例的
		 */
		Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
		if (CollectionUtil.isNotEmpty(beanMap)) {
			Set<Entry<Class<?>, Object>> beanMapEntrySet = beanMap.entrySet();
			for (Map.Entry<Class<?>, Object> beanMapEntry : beanMapEntrySet) {
				Class<?> beanClass = beanMapEntry.getKey();
				Object beanInstance = beanMapEntry.getValue();
				Field[] beanFields = beanClass.getDeclaredFields();
				if (ArrayUtil.isNotEmpty(beanFields)) {
					for (Field beanField : beanFields) {
						if (beanField.isAnnotationPresent(Inject.class)) {
							Class<?> fieldClass = beanField.getType();
							Object fieldInstance = beanMap.get(fieldClass);
							if (fieldInstance != null) {
								ReflectionUtil.setField(beanInstance, beanField, fieldInstance);
							}
						}
					}
				}
			}
		}
	}
}
